﻿using UnityEngine;
using System.Collections;

[AddComponentMenu ("Camera-Control/Mouse Orbit with zoom")]
public class MouseOrbit : MonoBehaviour
{
	// is used to follow target by position
	public Transform target;

	// actual distance from target
	public float distance = 2.5f;

	// speed for rotate transform in x and y direction
	public float xSpeed = 120.0f;
	public float ySpeed = 120.0f;

	// minum and maximum rotation in y direction
	public float yMinLimit = -12f;
	public float yMaxLimit = 40f;

	// minimum and maximum distance from target
	public float distanceMin = 2f;
	public float distanceMax = 6f;

	// current rotation angles
	private float x = 0.0f;
	private float y = 0.0f;

	// current colliding distance
	private float collidingDistance = 0.0f;

	// position offset for transform in y direction
	private float yOffset = 1.5f;

	public void Start ()
	{
		Vector3 angles = transform.eulerAngles;
		x = angles.y;
		y = angles.x;
	}

	/// <summary>
	/// LateUpdate - called after all Update functions have been called,
	/// a follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update
	/// </summary>
	public void LateUpdate ()
	{
		if (target == null) {
			return;
		}

		// check for objects between target and transform position
		RaycastHit hit;
		Vector3 pos = new Vector3 (target.position.x, target.position.y + yOffset, target.position.z);
		if (Physics.Linecast (pos, transform.position, out hit)) {
			// transform collides with target
			collidingDistance = distance;
			distance -= hit.distance;
		} else if (collidingDistance > 0) {
			// transform collides with target in last frame --> check if transform with last distance still collides with target
			float currentX = x + Input.GetAxis ("Mouse X") * xSpeed * collidingDistance * 0.02f;
			Quaternion currentRotation = Quaternion.Euler (y, currentX, 0);
			Vector3 currentPos = currentRotation * new Vector3 (0.0f, yOffset, -collidingDistance) + target.position;
			if (!Physics.Linecast (pos, currentPos, out hit)) {
				// transform does not collides with target any more
				distance = collidingDistance;
				collidingDistance = 0.0f;
			}
		}

		// check if transform does collides with target
		if (collidingDistance == 0.0f) {
			distance = Mathf.Clamp (distance - Input.GetAxis ("Mouse ScrollWheel") * 5, distanceMin, distanceMax); 
		}

		// check for mouse is moving
		if (Input.GetAxis ("Mouse X") != 0 || Input.GetAxis ("Mouse Y") != 0) {
			// calculate new angles
			x += Input.GetAxis ("Mouse X") * xSpeed * distance * 0.02f;
			y -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f;
			y = Mathf.Clamp (y, yMinLimit, yMaxLimit);
			// calculate new rotation
			Quaternion rotation = Quaternion.Euler (y, x, 0);
			// apply rotation and position to transform
			transform.rotation = rotation;
		} else {
			// update current x rotation angle (if transform changed we want to override current x rotation)
			x = transform.eulerAngles.y;
		}

		// calculate new position with new distance (mouse scroll)
		transform.position = transform.rotation * new Vector3 (0.0f, yOffset, -distance) + target.position;
	}

	//	public void OnDrawGizmos() {
	//		Vector3 vector = new Vector3 (target.position.x, target.position.y + yOffset, target.position.z);
	//		Gizmos.DrawLine (vector, transform.position);
	//	}

}
